package com.docmgmt.mvp.controller;

import com.docmgmt.mvp.dto.PagedResult;
import com.docmgmt.mvp.dto.Result;
import com.docmgmt.mvp.entity.FileEntity;
import com.docmgmt.mvp.exception.ForbiddenException;
import com.docmgmt.mvp.exception.UnauthorizedException;
import com.docmgmt.mvp.service.KnowledgeBaseService;
import com.docmgmt.mvp.service.PermissionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 知识库管理控制器（v3.0 文件映射 + RBAC 权限）
 *
 * v3.0 架构：
 * - 单一物理知识库：company_main_kb
 * - 文件→知识库 M:N 映射
 * - 逻辑知识库通过文件映射视图构建
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/knowledge-bases")
@RequiredArgsConstructor
public class KnowledgeBaseController {

    private final KnowledgeBaseService knowledgeBaseService;
    private final PermissionService permissionService;

    /**
     * 添加文件到知识库
     *
     * POST /api/v1/knowledge-bases/{kbId}/files?file_id=100
     *
     * @param kbId   知识库ID
     * @param fileId 文件ID
     * @return 成功响应
     */
    @PostMapping("/{kbId}/files")
    public Result<Void> addFileToKB(
            @PathVariable Long kbId,
            @RequestParam("file_id") Long fileId) {

        Long userId = getCurrentUserId();

        // 权限检查：kb:add_file
        if (!permissionService.checkPermission(userId, "kb:"+kbId, "add_file")) {
            throw new ForbiddenException("无权限向该知识库添加文件");
        }

        log.info("POST /api/v1/knowledge-bases/{}/files - userId={}, fileId={}", kbId, userId, fileId);

        knowledgeBaseService.addFileToKB(kbId, fileId, userId);
        return Result.success("文件已添加到知识库");
    }

    /**
     * 从知识库移除文件
     *
     * DELETE /api/v1/knowledge-bases/{kbId}/files/{fileId}
     *
     * @param kbId   知识库ID
     * @param fileId 文件ID
     * @return 成功响应
     */
    @DeleteMapping("/{kbId}/files/{fileId}")
    public Result<Void> removeFileFromKB(
            @PathVariable Long kbId,
            @PathVariable Long fileId) {

        Long userId = getCurrentUserId();

        // 权限检查：kb:remove_file
        if (!permissionService.checkPermission(userId, "kb:"+kbId, "remove_file")) {
            throw new ForbiddenException("无权限从该知识库移除文件");
        }

        log.info("DELETE /api/v1/knowledge-bases/{}/files/{} - userId={}", kbId, fileId, userId);

        knowledgeBaseService.removeFileFromKB(kbId, fileId, userId);
        return Result.success("文件已从知识库移除");
    }

    /**
     * 获取知识库中的文件列表
     *
     * GET /api/v1/knowledge-bases/{kbId}/files?page=1&page_size=20
     *
     * @param kbId     知识库ID
     * @param page     页码
     * @param pageSize 每页大小
     * @return 分页文件列表
     */
    @GetMapping("/{kbId}/files")
    public Result<PagedResult<FileEntity>> getKBFiles(
            @PathVariable Long kbId,
            @RequestParam(value = "page", required = false) Integer page,
            @RequestParam(value = "page_size", required = false) Integer pageSize) {

        Long userId = getCurrentUserId();

        // 权限检查：kb:read
        if (!permissionService.checkPermission(userId, "kb:"+kbId, "read")) {
            throw new ForbiddenException("无权限查看该知识库");
        }

        log.info("GET /api/v1/knowledge-bases/{}/files - userId={}, page={}", kbId, userId, page);

        PagedResult<FileEntity> result = knowledgeBaseService.getKBFiles(kbId, page, pageSize);
        return Result.success(result);
    }

    /**
     * 获取文件所属的知识库列表
     *
     * GET /api/files/{fileId}/knowledge-bases
     *
     * @param fileId 文件ID
     * @return 知识库ID列表
     */
    @GetMapping("/files/{fileId}/knowledge-bases")
    public Result<List<Long>> getFileKBs(@PathVariable Long fileId) {
        Long userId = getCurrentUserId();

        // 权限检查：file:read
        if (!permissionService.checkPermission(userId, "file:"+fileId, "read")) {
            throw new ForbiddenException("无权限查看该文件");
        }

        log.info("GET /api/files/{}/knowledge-bases - userId={}", fileId, userId);

        List<Long> kbIds = knowledgeBaseService.getFileKBs(fileId);
        return Result.success(kbIds);
    }

    /**
     * 触发知识库同步
     *
     * POST /api/v1/knowledge-bases/{kbId}/sync?file_id=100&action=UPLOAD
     *
     * @param kbId   知识库ID（暂未使用，v3.0 单一物理知识库）
     * @param fileId 文件ID
     * @param action 操作类型（UPLOAD/UPDATE/DELETE）
     * @return 成功响应
     */
    @PostMapping("/{kbId}/sync")
    public Result<Void> triggerKBSync(
            @PathVariable Long kbId,
            @RequestParam("file_id") Long fileId,
            @RequestParam("action") String action) {

        Long userId = getCurrentUserId();

        // 权限检查：kb:trigger_sync
        if (!permissionService.checkPermission(userId, "kb", "trigger_sync")) {
            throw new ForbiddenException("无权限触发知识库同步");
        }

        log.info("POST /api/v1/knowledge-bases/{}/sync - userId={}, fileId={}, action={}",
                kbId, userId, fileId, action);

        knowledgeBaseService.triggerKBSync(fileId, action);
        return Result.success("同步任务已触发");
    }

    /**
     * 批量添加文件到知识库
     *
     * POST /api/v1/knowledge-bases/{kbId}/files/batch
     *
     * @param kbId    知识库ID
     * @param fileIds 文件ID列表
     * @return 成功响应
     */
    @PostMapping("/{kbId}/files/batch")
    public Result<Void> batchAddFilesToKB(
            @PathVariable Long kbId,
            @RequestBody List<Long> fileIds) {

        Long userId = getCurrentUserId();

        // 权限检查：kb:add_file
        if (!permissionService.checkPermission(userId, "kb:"+kbId, "add_file")) {
            throw new ForbiddenException("无权限向该知识库添加文件");
        }

        log.info("POST /api/v1/knowledge-bases/{}/files/batch - userId={}, fileCount={}",
                kbId, userId, fileIds.size());

        knowledgeBaseService.batchAddFilesToKB(kbId, fileIds, userId);
        return Result.success(String.format("已添加 %d 个文件到知识库", fileIds.size()));
    }

    /**
     * 批量从知识库移除文件
     *
     * DELETE /api/v1/knowledge-bases/{kbId}/files/batch
     *
     * @param kbId    知识库ID
     * @param fileIds 文件ID列表
     * @return 成功响应
     */
    @DeleteMapping("/{kbId}/files/batch")
    public Result<Void> batchRemoveFilesFromKB(
            @PathVariable Long kbId,
            @RequestBody List<Long> fileIds) {

        Long userId = getCurrentUserId();

        // 权限检查：kb:remove_file
        if (!permissionService.checkPermission(userId, "kb:"+kbId, "remove_file")) {
            throw new ForbiddenException("无权限从该知识库移除文件");
        }

        log.info("DELETE /api/v1/knowledge-bases/{}/files/batch - userId={}, fileCount={}",
                kbId, userId, fileIds.size());

        knowledgeBaseService.batchRemoveFilesFromKB(kbId, fileIds, userId);
        return Result.success(String.format("已从知识库移除 %d 个文件", fileIds.size()));
    }

    /**
     * 获取或创建公司主知识库（v3.0）
     *
     * GET /api/v1/knowledge-bases/company-main
     *
     * @return 知识库ID
     */
    @GetMapping("/company-main")
    public Result<String> getCompanyMainKB() {
        Long userId = getCurrentUserId();

        // 权限检查：kb:read
        if (!permissionService.checkPermission(userId, "kb", "read")) {
            throw new ForbiddenException("无权限查看知识库");
        }

        log.info("GET /api/v1/knowledge-bases/company-main - userId={}", userId);

        String kbId = knowledgeBaseService.getOrCreateCompanyMainKB();
        return Result.success("公司主知识库ID", kbId);
    }

    /**
     * 清除知识库缓存（管理员操作）
     *
     * DELETE /api/v1/knowledge-bases/cache
     *
     * @return 成功响应
     */
    @DeleteMapping("/cache")
    public Result<Void> clearCache() {
        Long userId = getCurrentUserId();

        // 权限检查：system:admin（需要系统管理员权限）
        if (!permissionService.checkPermission(userId, "system", "admin")) {
            throw new ForbiddenException("无权限清除缓存");
        }

        log.info("DELETE /api/v1/knowledge-bases/cache - admin={}", userId);

        knowledgeBaseService.clearCache();
        return Result.success("知识库缓存已清除");
    }

    /**
     * 从Spring Security上下文获取当前用户ID
     */
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new UnauthorizedException("未登录或认证已过期");
        }

        Object principal = authentication.getPrincipal();
        if (principal instanceof Long) {
            return (Long) principal;
        }

        throw new UnauthorizedException("无效的认证信息");
    }
}
